// Copyright (c) 2013-2019 Intel Corporation
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.

#include "spl/mfx_omx_avc_bitstream.h"

namespace AVCParser
{

mfxStatus DecodeExpGolombOne(mfxU32 **ppBitStream, mfxI32 *pBitOffset,
                                                      mfxI32 *pDst,
                                                      mfxI32 isSigned);

enum
{
    SCLFLAT16     = 0,
    SCLDEFAULT    = 1,
    SCLREDEFINED  = 2
};

const mfxU32 bits_data[] =
{
    (((mfxU32)0x01 << (0)) - 1),
    (((mfxU32)0x01 << (1)) - 1),
    (((mfxU32)0x01 << (2)) - 1),
    (((mfxU32)0x01 << (3)) - 1),
    (((mfxU32)0x01 << (4)) - 1),
    (((mfxU32)0x01 << (5)) - 1),
    (((mfxU32)0x01 << (6)) - 1),
    (((mfxU32)0x01 << (7)) - 1),
    (((mfxU32)0x01 << (8)) - 1),
    (((mfxU32)0x01 << (9)) - 1),
    (((mfxU32)0x01 << (10)) - 1),
    (((mfxU32)0x01 << (11)) - 1),
    (((mfxU32)0x01 << (12)) - 1),
    (((mfxU32)0x01 << (13)) - 1),
    (((mfxU32)0x01 << (14)) - 1),
    (((mfxU32)0x01 << (15)) - 1),
    (((mfxU32)0x01 << (16)) - 1),
    (((mfxU32)0x01 << (17)) - 1),
    (((mfxU32)0x01 << (18)) - 1),
    (((mfxU32)0x01 << (19)) - 1),
    (((mfxU32)0x01 << (20)) - 1),
    (((mfxU32)0x01 << (21)) - 1),
    (((mfxU32)0x01 << (22)) - 1),
    (((mfxU32)0x01 << (23)) - 1),
    (((mfxU32)0x01 << (24)) - 1),
    (((mfxU32)0x01 << (25)) - 1),
    (((mfxU32)0x01 << (26)) - 1),
    (((mfxU32)0x01 << (27)) - 1),
    (((mfxU32)0x01 << (28)) - 1),
    (((mfxU32)0x01 << (29)) - 1),
    (((mfxU32)0x01 << (30)) - 1),
    (((mfxU32)0x01 << (31)) - 1),
    ((mfxU32)0xFFFFFFFF),
};

const mfxU8 default_intra_scaling_list4x4[16]=
{
     6, 13, 20, 28, 13, 20, 28, 32, 20, 28, 32, 37, 28, 32, 37, 42
};
const mfxU8 default_inter_scaling_list4x4[16]=
{
    10, 14, 20, 24, 14, 20, 24, 27, 20, 24, 27, 30, 24, 27, 30, 34
};

const mfxU8 default_intra_scaling_list8x8[64]=
{
     6, 10, 13, 16, 18, 23, 25, 27, 10, 11, 16, 18, 23, 25, 27, 29,
    13, 16, 18, 23, 25, 27, 29, 31, 16, 18, 23, 25, 27, 29, 31, 33,
    18, 23, 25, 27, 29, 31, 33, 36, 23, 25, 27, 29, 31, 33, 36, 38,
    25, 27, 29, 31, 33, 36, 38, 40, 27, 29, 31, 33, 36, 38, 40, 42
};
const mfxU8 default_inter_scaling_list8x8[64]=
{
     9, 13, 15, 17, 19, 21, 22, 24, 13, 13, 17, 19, 21, 22, 24, 25,
    15, 17, 19, 21, 22, 24, 25, 27, 17, 19, 21, 22, 24, 25, 27, 28,
    19, 21, 22, 24, 25, 27, 28, 30, 21, 22, 24, 25, 27, 28, 30, 32,
    22, 24, 25, 27, 28, 30, 32, 33, 24, 25, 27, 28, 30, 32, 33, 35
};

const mfxI32 pre_norm_adjust_index4x4[16] =
{// 0 1 2 3
    0,2,0,2,//0
    2,1,2,1,//1
    0,2,0,2,//2
    2,1,2,1 //3
};

const mfxI32 pre_norm_adjust4x4[6][3] =
{
    {10,16,13},
    {11,18,14},
    {13,20,16},
    {14,23,18},
    {16,25,20},
    {18,29,23}
};

const mfxI32 pre_norm_adjust8x8[6][6] =
{
    {20, 18, 32, 19, 25, 24},
    {22, 19, 35, 21, 28, 26},
    {26, 23, 42, 24, 33, 31},
    {28, 25, 45, 26, 35, 33},
    {32, 28, 51, 30, 40, 38},
    {36, 32, 58, 34, 46, 43}
};
const mfxI32 pre_norm_adjust_index8x8[64] =
{// 0 1 2 3 4 5 6 7
    0,3,4,3,0,3,4,3,//0
    3,1,5,1,3,1,5,1,//1
    4,5,2,5,4,5,2,5,//2
    3,1,5,1,3,1,5,1,//3
    0,3,4,3,0,3,4,3,//4
    3,1,5,1,3,1,5,1,//5
    4,5,2,5,4,5,2,5,//6
    3,1,5,1,3,1,5,1 //7
};

const mfxI32 mp_scan4x4[2][16] =
{
    {
        0,  1,  4,  8,
        5,  2,  3,  6,
        9,  12, 13, 10,
        7,  11, 14, 15
    },
    {
        0,  4,  1,  8,
        12, 5,  9,  13,
        2,  6,  10, 14,
        3,  7,  11, 15
    }
};

const mfxI32 hp_scan8x8[2][64] =
{
    //8x8 zigzag scan
    {
        0, 1, 8,16, 9, 2, 3,10,
        17,24,32,25,18,11, 4, 5,
        12,19,26,33,40,48,41,34,
        27,20,13, 6, 7,14,21,28,
        35,42,49,56,57,50,43,36,
        29,22,15,23,30,37,44,51,
        58,59,52,45,38,31,39,46,
        53,60,61,54,47,55,62,63
    },
    //8x8 field scan
    {
        0, 8,16, 1, 9,24,32,17,
        2,25,40,48,56,33,10, 3,
        18,41,49,57,26,11, 4,19,
        34,42,50,58,27,12, 5,20,
        35,43,51,59,28,13, 6,21,
        36,44,52,60,29,14,22,37,
        45,53,61,30, 7,15,38,46,
        54,62,23,31,39,47,55,63
    }
};

#define avcSkipNBits(current_data, offset, nbits) \
{ \
    /* check error(s) */ \
    SAMPLE_ASSERT((nbits) > 0 && (nbits) <= 32); \
    SAMPLE_ASSERT(offset >= 0 && offset <= 31); \
    /* decrease number of available bits */ \
    offset -= (nbits); \
    /* normalize bitstream pointer */ \
    if (0 > offset) \
    { \
        offset += 32; \
        current_data++; \
    } \
    /* check error(s) again */ \
    SAMPLE_ASSERT(offset >= 0 && offset <= 31); \
 }

#define avcGetBits8( current_data, offset, data) \
    _avcGetBits(current_data, offset, 8, data);


#define avcUngetNBits(current_data, offset, nbits) \
{ \
    SAMPLE_ASSERT(offset >= 0 && offset <= 31); \
 \
    offset += (nbits); \
    if (offset > 31) \
    { \
        offset -= 32; \
        current_data--; \
    } \
 \
    SAMPLE_ASSERT(offset >= 0 && offset <= 31); \
}

#define avcUngetBits32(current_data, offset) \
    SAMPLE_ASSERT(offset >= 0 && offset <= 31); \
    current_data--;

#define avcAlignBSPointerRight(current_data, offset) \
{ \
    if ((offset & 0x07) != 0x07) \
    { \
        offset = (offset | 0x07) - 8; \
        if (offset == -1) \
        { \
            offset = 31; \
            current_data++; \
        } \
    } \
}

inline void FillFlatScalingList4x4(AVCScalingList4x4 *scl)
{
    for (mfxI32 i=0;i<16;i++)
        scl->ScalingListCoeffs[i] = 16;
}

inline void FillFlatScalingList8x8(AVCScalingList8x8 *scl)
{
    for (mfxI32 i=0;i<64;i++)
        scl->ScalingListCoeffs[i] = 16;
}

inline void FillScalingList4x4(AVCScalingList4x4 *scl_dst,mfxU8 *coefs_src)
{
    for (mfxI32 i=0;i<16;i++)
        scl_dst->ScalingListCoeffs[i] = coefs_src[i];
}

inline void FillScalingList8x8(AVCScalingList8x8 *scl_dst,mfxU8 *coefs_src)
{
    for (mfxI32 i=0;i<64;i++)
        scl_dst->ScalingListCoeffs[i] = coefs_src[i];
}

AVCBaseBitstream::AVCBaseBitstream()
	: m_pbs(0)
	, m_bitOffset(31)
	, m_pbsBase(0)
	, m_maxBsSize(0)
{
    //Reset(0, 0); 
    //Remove duplicated init task.
}

AVCBaseBitstream::AVCBaseBitstream(mfxU8 * const pb, const mfxU32 maxsize)
{
    Reset(pb, maxsize);
}

AVCBaseBitstream::~AVCBaseBitstream()
{
}

void AVCBaseBitstream::Reset(mfxU8 * const pb, const mfxU32 maxsize)
{
    m_pbs       = (mfxU32*)pb;
    m_pbsBase   = (mfxU32*)pb;
    m_bitOffset = 31;
    m_maxBsSize    = maxsize;

} // void Reset(mfxU8 * const pb, const mfxU32 maxsize)

void AVCBaseBitstream::Reset(mfxU8 * const pb, mfxI32 offset, const mfxU32 maxsize)
{
    m_pbs       = (mfxU32*)pb;
    m_pbsBase   = (mfxU32*)pb;
    m_bitOffset = offset;
    m_maxBsSize = maxsize;

} // void Reset(mfxU8 * const pb, mfxI32 offset, const mfxU32 maxsize)

mfxStatus AVCBaseBitstream::GetNALUnitType( NAL_Unit_Type &uNALUnitType,mfxU8 &uNALStorageIDC)
{
    mfxU32 code;
    avcGetBits8(m_pbs, m_bitOffset, code);

    uNALStorageIDC = (mfxU8)((code & NAL_STORAGE_IDC_BITS)>>5);
    uNALUnitType = (NAL_Unit_Type)(code & NAL_UNITTYPE_BITS);
    return MFX_ERR_NONE;
}    // GetNALUnitType

mfxI32 AVCBaseBitstream::GetVLCElement(bool bIsSigned)
{
    mfxI32 sval = 0;

    mfxStatus res = DecodeExpGolombOne(&m_pbs, &m_bitOffset, &sval, bIsSigned);

    if (res < MFX_ERR_NONE)
        throw AVC_exception(MFX_ERR_UNDEFINED_BEHAVIOR);

    return sval;
}

void AVCBaseBitstream::AlignPointerRight(void)
{
    avcAlignBSPointerRight(m_pbs, m_bitOffset);

} // void AVCBitstream::AlignPointerRight(void)

bool AVCBaseBitstream::More_RBSP_Data()
{
    mfxI32 code, tmp;
    mfxU32* ptr_state = m_pbs;
    mfxI32  bit_state = m_bitOffset;

    SAMPLE_ASSERT(m_bitOffset >= 0 && m_bitOffset <= 31);

    mfxI32 remaining_bytes = (mfxI32)BytesLeft();

    if (remaining_bytes <= 0)
        return false;

    // get top bit, it can be "rbsp stop" bit
    avcGetNBits(m_pbs, m_bitOffset, 1, code);

    // get remain bits, which is less then byte
    tmp = (m_bitOffset + 1) % 8;

    if(tmp)
    {
        avcGetNBits(m_pbs, m_bitOffset, tmp, code);
        if ((code << (8 - tmp)) & 0x7f)    // most sig bit could be rbsp stop bit
        {
            m_pbs = ptr_state;
            m_bitOffset = bit_state;
            // there are more data
            return true;
        }
    }

    remaining_bytes = (mfxI32)BytesLeft();

    // run through remain bytes
    while (0 < remaining_bytes)
    {
        avcGetBits8(m_pbs, m_bitOffset, code);

        if (code)
        {
            m_pbs = ptr_state;
            m_bitOffset = bit_state;
            // there are more data
            return true;
        }

        remaining_bytes -= 1;
    }

    return false;
}

AVCHeadersBitstream::AVCHeadersBitstream()
    : AVCBaseBitstream()
{
}

AVCHeadersBitstream::AVCHeadersBitstream(mfxU8 * const pb, const mfxU32 maxsize)
    : AVCBaseBitstream(pb, maxsize)
{
}

// ---------------------------------------------------------------------------
//  AVCBitstream::GetSequenceParamSet()
//    Read sequence parameter set data from bitstream.
// ---------------------------------------------------------------------------
mfxStatus AVCHeadersBitstream::GetSequenceParamSet(AVCSeqParamSet *sps)
{
    // Not all members of the seq param set structure are contained in all
    // seq param sets. So start by init all to zero.
    mfxStatus ps = MFX_ERR_NONE;
    sps->Reset();

    // profile
    sps->profile_idc = (mfxU8)GetBits(8);

    switch (sps->profile_idc)
    {
    case AVC_PROFILE_BASELINE:
    case AVC_PROFILE_MAIN:
    case AVC_PROFILE_SCALABLE_BASELINE:
    case AVC_PROFILE_SCALABLE_HIGH:
    case AVC_PROFILE_EXTENDED:
    case AVC_PROFILE_HIGH:
    case AVC_PROFILE_HIGH10:
    case AVC_PROFILE_MULTIVIEW_HIGH:
    case AVC_PROFILE_HIGH422:
    case AVC_PROFILE_STEREO_HIGH:
    case AVC_PROFILE_HIGH444:
    case AVC_PROFILE_ADVANCED444_INTRA:
    case AVC_PROFILE_ADVANCED444:
        break;
    default:
        return MFX_ERR_UNDEFINED_BEHAVIOR;
    }

    sps->constrained_set0_flag = (mfxU8)Get1Bit();

    sps->constrained_set1_flag = (mfxU8)Get1Bit();

    sps->constrained_set2_flag = (mfxU8)Get1Bit();

    sps->constrained_set3_flag = (mfxU8)Get1Bit();

    // skip 4 zero bits
    GetBits(4);

    sps->level_idc = (mfxU8)GetBits(8);

    switch(sps->level_idc)
    {
    case AVC_LEVEL_1:
    case AVC_LEVEL_11:
    case AVC_LEVEL_12:
    case AVC_LEVEL_13:

    case AVC_LEVEL_2:
    case AVC_LEVEL_21:
    case AVC_LEVEL_22:

    case AVC_LEVEL_3:
    case AVC_LEVEL_31:
    case AVC_LEVEL_32:

    case AVC_LEVEL_4:
    case AVC_LEVEL_41:
    case AVC_LEVEL_42:

    case AVC_LEVEL_5:
    case AVC_LEVEL_51:
        break;
    default:
        return MFX_ERR_UNDEFINED_BEHAVIOR;
    }

    // id
    mfxI32 sps_id = GetVLCElement(false);
    if (sps_id > MAX_NUM_SEQ_PARAM_SETS - 1)
    {
        return MFX_ERR_UNDEFINED_BEHAVIOR;
    }

    sps->seq_parameter_set_id = (mfxU8)sps_id;

    // see 7.3.2.1.1 "Sequence parameter set data syntax"
    // chapter of H264 standard for full list of profiles with chrominance
    if ((AVC_PROFILE_SCALABLE_BASELINE == sps->profile_idc) ||
        (AVC_PROFILE_SCALABLE_HIGH == sps->profile_idc) ||
        (AVC_PROFILE_HIGH == sps->profile_idc) ||
        (AVC_PROFILE_HIGH10 == sps->profile_idc) ||
        (AVC_PROFILE_MULTIVIEW_HIGH == sps->profile_idc) ||
        (AVC_PROFILE_HIGH422 == sps->profile_idc) ||
        (AVC_PROFILE_STEREO_HIGH == sps->profile_idc) ||
        (244 == sps->profile_idc) ||
        (44 == sps->profile_idc))
    {
        mfxU32 chroma_format_idc = GetVLCElement(false);

        if (chroma_format_idc > 3)
        {
            return MFX_ERR_UNDEFINED_BEHAVIOR;
        }

        sps->chroma_format_idc = (mfxU8)chroma_format_idc;
        if (sps->chroma_format_idc==3)
        {
            sps->residual_colour_transform_flag = (mfxU8) Get1Bit();
        }

        mfxU32 bit_depth_luma = GetVLCElement(false) + 8;
        mfxU32 bit_depth_chroma = GetVLCElement(false) + 8;

        if (bit_depth_luma > 16 || bit_depth_chroma > 16)
        {
            return MFX_ERR_UNDEFINED_BEHAVIOR;
        }

        sps->bit_depth_luma = (mfxU8)bit_depth_luma;
        sps->bit_depth_chroma = (mfxU8)bit_depth_chroma;

        if (!chroma_format_idc)
            sps->bit_depth_chroma = sps->bit_depth_luma;

        SAMPLE_ASSERT(!sps->residual_colour_transform_flag);
        if (sps->residual_colour_transform_flag == 1)
        {
            return MFX_ERR_UNDEFINED_BEHAVIOR;
        }

        sps->qpprime_y_zero_transform_bypass_flag = (mfxU8)Get1Bit();
        sps->seq_scaling_matrix_present_flag = (mfxU8)Get1Bit();
        if(sps->seq_scaling_matrix_present_flag)
        {
            // 0
            if(Get1Bit())
            {
                GetScalingList4x4(&sps->ScalingLists4x4[0],(mfxU8*)default_intra_scaling_list4x4,&sps->type_of_scaling_list_used[0]);
            }
            else
            {
                FillScalingList4x4(&sps->ScalingLists4x4[0],(mfxU8*) default_intra_scaling_list4x4);
                sps->type_of_scaling_list_used[0] = SCLDEFAULT;
            }
            // 1
            if(Get1Bit())
            {
                GetScalingList4x4(&sps->ScalingLists4x4[1],(mfxU8*) default_intra_scaling_list4x4,&sps->type_of_scaling_list_used[1]);
            }
            else
            {
                FillScalingList4x4(&sps->ScalingLists4x4[1],(mfxU8*) sps->ScalingLists4x4[0].ScalingListCoeffs);
                sps->type_of_scaling_list_used[1] = SCLDEFAULT;
            }
            // 2
            if(Get1Bit())
            {
                GetScalingList4x4(&sps->ScalingLists4x4[2],(mfxU8*) default_intra_scaling_list4x4,&sps->type_of_scaling_list_used[2]);
            }
            else
            {
                FillScalingList4x4(&sps->ScalingLists4x4[2],(mfxU8*) sps->ScalingLists4x4[1].ScalingListCoeffs);
                sps->type_of_scaling_list_used[2] = SCLDEFAULT;
            }
            // 3
            if(Get1Bit())
            {
                GetScalingList4x4(&sps->ScalingLists4x4[3],(mfxU8*)default_inter_scaling_list4x4,&sps->type_of_scaling_list_used[3]);
            }
            else
            {
                FillScalingList4x4(&sps->ScalingLists4x4[3],(mfxU8*) default_inter_scaling_list4x4);
                sps->type_of_scaling_list_used[3] = SCLDEFAULT;
            }
            // 4
            if(Get1Bit())
            {
                GetScalingList4x4(&sps->ScalingLists4x4[4],(mfxU8*) default_inter_scaling_list4x4,&sps->type_of_scaling_list_used[4]);
            }
            else
            {
                FillScalingList4x4(&sps->ScalingLists4x4[4],(mfxU8*) sps->ScalingLists4x4[3].ScalingListCoeffs);
                sps->type_of_scaling_list_used[4] = SCLDEFAULT;
            }
            // 5
            if(Get1Bit())
            {
                GetScalingList4x4(&sps->ScalingLists4x4[5],(mfxU8*) default_inter_scaling_list4x4,&sps->type_of_scaling_list_used[5]);
            }
            else
            {
                FillScalingList4x4(&sps->ScalingLists4x4[5],(mfxU8*) sps->ScalingLists4x4[4].ScalingListCoeffs);
                sps->type_of_scaling_list_used[5] = SCLDEFAULT;
            }

            // 0
            if(Get1Bit())
            {
                GetScalingList8x8(&sps->ScalingLists8x8[0],(mfxU8*)default_intra_scaling_list8x8,&sps->type_of_scaling_list_used[6]);
            }
            else
            {
                FillScalingList8x8(&sps->ScalingLists8x8[0],(mfxU8*) default_intra_scaling_list8x8);
                sps->type_of_scaling_list_used[6] = SCLDEFAULT;
            }
            // 1
            if(Get1Bit())
            {
                GetScalingList8x8(&sps->ScalingLists8x8[1],(mfxU8*) default_inter_scaling_list8x8,&sps->type_of_scaling_list_used[7]);
            }
            else
            {
                FillScalingList8x8(&sps->ScalingLists8x8[1],(mfxU8*) default_inter_scaling_list8x8);
                sps->type_of_scaling_list_used[7] = SCLDEFAULT;
            }

        }
        else
        {
            mfxI32 i;

            for (i = 0; i < 6; i += 1)
            {
                FillFlatScalingList4x4(&sps->ScalingLists4x4[i]);
            }
            for (i = 0; i < 2; i += 1)
            {
                FillFlatScalingList8x8(&sps->ScalingLists8x8[i]);
            }
        }
    }
    else
    {
        sps->chroma_format_idc = 1;
        sps->bit_depth_luma = 8;
        sps->bit_depth_chroma = 8;

        SetDefaultScalingLists(sps);
    }

    // log2 max frame num (bitstream contains value - 4)
    mfxU32 log2_max_frame_num = GetVLCElement(false) + 4;
    sps->log2_max_frame_num = (mfxU8)log2_max_frame_num;

    if (log2_max_frame_num > 16 || log2_max_frame_num < 4)
    {
        return MFX_ERR_UNDEFINED_BEHAVIOR;
    }

    // pic order cnt type (0..2)
    mfxU32 pic_order_cnt_type = GetVLCElement(false);
    sps->pic_order_cnt_type = (mfxU8)pic_order_cnt_type;
    if (pic_order_cnt_type > 2)
    {
        return MFX_ERR_UNDEFINED_BEHAVIOR;
    }

    if (sps->pic_order_cnt_type == 0)
    {
        // log2 max pic order count lsb (bitstream contains value - 4)
        mfxU32 log2_max_pic_order_cnt_lsb = GetVLCElement(false) + 4;
        sps->log2_max_pic_order_cnt_lsb = (mfxU8)log2_max_pic_order_cnt_lsb;

        if (log2_max_pic_order_cnt_lsb > 16 || log2_max_pic_order_cnt_lsb < 4)
            return MFX_ERR_UNDEFINED_BEHAVIOR;

        sps->MaxPicOrderCntLsb = (1 << sps->log2_max_pic_order_cnt_lsb);
    }
    else if (sps->pic_order_cnt_type == 1)
    {
        sps->delta_pic_order_always_zero_flag = (mfxU8)Get1Bit();
        sps->offset_for_non_ref_pic = GetVLCElement(true);
        sps->offset_for_top_to_bottom_field = GetVLCElement(true);
        sps->num_ref_frames_in_pic_order_cnt_cycle = GetVLCElement(false);

        if (sps->num_ref_frames_in_pic_order_cnt_cycle > 255)
            return MFX_ERR_UNDEFINED_BEHAVIOR;

        // get offsets
        for (mfxU32 i = 0; i < sps->num_ref_frames_in_pic_order_cnt_cycle; i++)
        {
            sps->poffset_for_ref_frame[i] = GetVLCElement(true);
        }
    }    // pic order count type 1

    // num ref frames
    sps->num_ref_frames = GetVLCElement(false);
    if (sps->num_ref_frames > 16)
        return MFX_ERR_UNDEFINED_BEHAVIOR;

    sps->gaps_in_frame_num_value_allowed_flag = (mfxU8)Get1Bit();

    // picture width in MBs (bitstream contains value - 1)
    sps->frame_width_in_mbs = GetVLCElement(false) + 1;

    // picture height in MBs (bitstream contains value - 1)
    sps->frame_height_in_mbs = GetVLCElement(false) + 1;

    sps->frame_mbs_only_flag = (mfxU8)Get1Bit();
    sps->frame_height_in_mbs  = (2-sps->frame_mbs_only_flag)*sps->frame_height_in_mbs;
    if (sps->frame_mbs_only_flag == 0)
    {
        sps->mb_adaptive_frame_field_flag = (mfxU8)Get1Bit();
    }
    sps->direct_8x8_inference_flag = (mfxU8)Get1Bit();
    if (sps->frame_mbs_only_flag==0)
    {
        sps->direct_8x8_inference_flag = 1;
    }
    sps->frame_cropping_flag = (mfxU8)Get1Bit();

    if (sps->frame_cropping_flag)
    {
        sps->frame_cropping_rect_left_offset      = GetVLCElement(false);
        sps->frame_cropping_rect_right_offset     = GetVLCElement(false);
        sps->frame_cropping_rect_top_offset       = GetVLCElement(false);
        sps->frame_cropping_rect_bottom_offset    = GetVLCElement(false);
    } // don't need else because we zeroid structure

    sps->vui_parameters_present_flag = (mfxU8)Get1Bit();
    if (sps->vui_parameters_present_flag)
    {
        if (ps == MFX_ERR_NONE)
            ps = GetVUIParam(sps);
    }

    return ps;
}    // GetSequenceParamSet

mfxStatus AVCHeadersBitstream::GetVUIParam(AVCSeqParamSet *sps)
{
    mfxStatus ps=MFX_ERR_NONE;
    sps->aspect_ratio_info_present_flag = (mfxU8) Get1Bit();

    sps->sar_width = 1; // default values
    sps->sar_height = 1;

    if (sps->aspect_ratio_info_present_flag)
    {
        sps->aspect_ratio_idc = (mfxU8) GetBits(8);
        if (sps->aspect_ratio_idc  ==  255) {
            sps->sar_width = (mfxU16) GetBits(16);
            sps->sar_height = (mfxU16) GetBits(16);
        }
    }

    sps->overscan_info_present_flag = (mfxU8) Get1Bit();
    if( sps->overscan_info_present_flag )
        sps->overscan_appropriate_flag = (mfxU8) Get1Bit();
    sps->video_signal_type_present_flag = (mfxU8) Get1Bit();
    if( sps->video_signal_type_present_flag ) {
        sps->video_format = (mfxU8) GetBits(3);
        sps->video_full_range_flag = (mfxU8) Get1Bit();
        sps->colour_description_present_flag = (mfxU8) Get1Bit();
        if( sps->colour_description_present_flag ) {
            sps->colour_primaries = (mfxU8) GetBits(8);
            sps->transfer_characteristics = (mfxU8) GetBits(8);
            sps->matrix_coefficients = (mfxU8) GetBits(8);
        }
    }
    sps->chroma_loc_info_present_flag = (mfxU8) Get1Bit();
    if( sps->chroma_loc_info_present_flag ) {
        sps->chroma_sample_loc_type_top_field = (mfxU8) GetVLCElement(false);
        sps->chroma_sample_loc_type_bottom_field = (mfxU8) GetVLCElement(false);
    }
    sps->timing_info_present_flag = (mfxU8) Get1Bit();

    if (sps->timing_info_present_flag)
    {
        sps->num_units_in_tick = GetBits(32);
        sps->time_scale = GetBits(32);
        sps->fixed_frame_rate_flag = (mfxU8) Get1Bit();

        if (!sps->num_units_in_tick || !sps->time_scale)
            sps->timing_info_present_flag = 0;
    }

    sps->nal_hrd_parameters_present_flag = (mfxU8) Get1Bit();
    if( sps->nal_hrd_parameters_present_flag )
        ps=GetHRDParam(sps);
    sps->vcl_hrd_parameters_present_flag = (mfxU8) Get1Bit();
    if( sps->vcl_hrd_parameters_present_flag )
        ps=GetHRDParam(sps);
    if( sps->nal_hrd_parameters_present_flag  ||  sps->vcl_hrd_parameters_present_flag )
        sps->low_delay_hrd_flag = (mfxU8) Get1Bit();
    sps->pic_struct_present_flag  = (mfxU8) Get1Bit();
    sps->bitstream_restriction_flag = (mfxU8) Get1Bit();
    if( sps->bitstream_restriction_flag ) {
        sps->motion_vectors_over_pic_boundaries_flag = (mfxU8) Get1Bit();
        sps->max_bytes_per_pic_denom = (mfxU8) GetVLCElement(false);
        sps->max_bits_per_mb_denom = (mfxU8) GetVLCElement(false);
        sps->log2_max_mv_length_horizontal = (mfxU8) GetVLCElement(false);
        sps->log2_max_mv_length_vertical = (mfxU8) GetVLCElement(false);
        sps->num_reorder_frames = (mfxU8) GetVLCElement(false);
        sps->max_dec_frame_buffering = (mfxU8) GetVLCElement(false);
    }
    return ps;
}

mfxStatus AVCHeadersBitstream::GetHRDParam(AVCSeqParamSet *sps)
{
    mfxStatus ps=MFX_ERR_NONE;
    mfxI32 cpb_cnt = GetVLCElement(false) + 1;

    if (cpb_cnt >= 32)
    {
        return MFX_ERR_UNDEFINED_BEHAVIOR;
    }

    sps->cpb_cnt = (mfxU8)cpb_cnt;

    sps->bit_rate_scale = (mfxU8) GetBits(4);
    sps->cpb_size_scale = (mfxU8) GetBits(4);
    for( mfxI32 idx= 0; idx < sps->cpb_cnt; idx++ ) {
        sps->bit_rate_value[ idx ] = (mfxU32) (GetVLCElement(false)+1);
        sps->cpb_size_value[ idx ] = (mfxU32) ((GetVLCElement(false)+1));
        sps->cbr_flag[ idx ] = (mfxU8) Get1Bit();
    }
    sps->initial_cpb_removal_delay_length = (mfxU8)(GetBits(5)+1);
    sps->cpb_removal_delay_length = (mfxU8)(GetBits(5)+1);
    sps->dpb_output_delay_length = (mfxU8) (GetBits(5)+1);
    sps->time_offset_length = (mfxU8) GetBits(5);
    return ps;

}

// ---------------------------------------------------------------------------
//    Read sequence parameter set extension data from bitstream.
// ---------------------------------------------------------------------------
mfxStatus AVCHeadersBitstream::GetSequenceParamSetExtension(AVCSeqParamSetExtension *sps_ex)
{
    // Not all members of the seq param set structure are contained in all
    // seq param sets. So start by init all to zero.
    mfxStatus ps = MFX_ERR_NONE;
    sps_ex->Reset();

    mfxU32 seq_parameter_set_id = GetVLCElement(false);
    sps_ex->seq_parameter_set_id = (mfxU8)seq_parameter_set_id;
    if (seq_parameter_set_id > MAX_NUM_SEQ_PARAM_SETS-1)
    {
        return MFX_ERR_UNDEFINED_BEHAVIOR;
    }

    mfxU32 aux_format_idc = GetVLCElement(false);
    sps_ex->aux_format_idc = (mfxU8)aux_format_idc;
    if (aux_format_idc > 3)
    {
        return MFX_ERR_UNDEFINED_BEHAVIOR;
    }

    if (sps_ex->aux_format_idc != 1 && sps_ex->aux_format_idc != 2)
        sps_ex->aux_format_idc = 0;

    if (sps_ex->aux_format_idc)
    {
        mfxU32 bit_depth_aux = GetVLCElement(false) + 8;
        sps_ex->bit_depth_aux = (mfxU8)bit_depth_aux;
        if (bit_depth_aux > 12)
        {
            return MFX_ERR_UNDEFINED_BEHAVIOR;
        }

        sps_ex->alpha_incr_flag = (mfxU8)Get1Bit();
        sps_ex->alpha_opaque_value = (mfxU8)GetBits(sps_ex->bit_depth_aux + 1);
        sps_ex->alpha_transparent_value = (mfxU8)GetBits(sps_ex->bit_depth_aux + 1);
    }

    sps_ex->additional_extension_flag = (mfxU8)Get1Bit();

    return ps;
}    // GetSequenceParamSetExtension

mfxStatus AVCHeadersBitstream::GetPictureParamSetPart1(AVCPicParamSet *pps)
{
    // Not all members of the pic param set structure are contained in all
    // pic param sets. So start by init all to zero.
    pps->Reset();

    // id
    mfxU32 pic_parameter_set_id = GetVLCElement(false);
    pps->pic_parameter_set_id = (mfxU16)pic_parameter_set_id;
    if (pic_parameter_set_id > MAX_NUM_PIC_PARAM_SETS-1)
    {
        return MFX_ERR_UNDEFINED_BEHAVIOR;
    }

    // seq param set referred to by this pic param set
    mfxU32 seq_parameter_set_id = GetVLCElement(false);
    pps->seq_parameter_set_id = (mfxU8)seq_parameter_set_id;
    if (seq_parameter_set_id > MAX_NUM_SEQ_PARAM_SETS-1)
    {
        return MFX_ERR_UNDEFINED_BEHAVIOR;
    }

    return MFX_ERR_NONE;
}    // GetPictureParamSetPart1

// Number of bits required to code slice group ID, index is num_slice_groups - 2
static const mfxU8 SGIdBits[7] = {1,2,2,3,3,3,3};

// ---------------------------------------------------------------------------
//    Read picture parameter set data from bitstream.
// ---------------------------------------------------------------------------
mfxStatus AVCHeadersBitstream::GetPictureParamSetPart2(AVCPicParamSet  *pps,
                                              const AVCSeqParamSet *sps)
{
    pps->entropy_coding_mode = (mfxU8)Get1Bit();


    pps->pic_order_present_flag = (mfxU8)Get1Bit();

    // number of slice groups, bitstream has value - 1
    pps->num_slice_groups = GetVLCElement(false) + 1;
    if (pps->num_slice_groups != 1)
    {
        mfxU32 slice_group;
        mfxU32 PicSizeInMapUnits;    // for range checks

        PicSizeInMapUnits = sps->frame_width_in_mbs * sps->frame_height_in_mbs;
            // TBD: needs adjust for fields

        if (pps->num_slice_groups > MAX_NUM_SLICE_GROUPS)
        {
            return MFX_ERR_UNDEFINED_BEHAVIOR;
        }

        mfxU32 slice_group_map_type = GetVLCElement(false);
        pps->SliceGroupInfo.slice_group_map_type = (mfxU8)slice_group_map_type;

        if (slice_group_map_type > 6)
            return MFX_ERR_UNDEFINED_BEHAVIOR;

        // Get additional, map type dependent slice group data
        switch (pps->SliceGroupInfo.slice_group_map_type)
        {
        case 0:
            for (slice_group=0; slice_group<pps->num_slice_groups; slice_group++)
            {
                // run length, bitstream has value - 1
                pps->SliceGroupInfo.run_length[slice_group] = GetVLCElement(false) + 1;

                if (pps->SliceGroupInfo.run_length[slice_group] > PicSizeInMapUnits)
                {
                    return MFX_ERR_UNDEFINED_BEHAVIOR;
                }
            }
            break;
        case 1:
            // no additional info
            break;
        case 2:
            for (slice_group=0; slice_group<(mfxU32)(pps->num_slice_groups-1); slice_group++)
            {
                pps->SliceGroupInfo.t1.top_left[slice_group] = GetVLCElement(false);
                pps->SliceGroupInfo.t1.bottom_right[slice_group] = GetVLCElement(false);

                // check for legal values
                if (pps->SliceGroupInfo.t1.top_left[slice_group] >
                    pps->SliceGroupInfo.t1.bottom_right[slice_group])
                {
                    return MFX_ERR_UNDEFINED_BEHAVIOR;
                }
                if (pps->SliceGroupInfo.t1.bottom_right[slice_group] >= PicSizeInMapUnits)
                {
                    return MFX_ERR_UNDEFINED_BEHAVIOR;
                }
                if ((pps->SliceGroupInfo.t1.top_left[slice_group] %
                    sps->frame_width_in_mbs) >
                    (pps->SliceGroupInfo.t1.bottom_right[slice_group] %
                    sps->frame_width_in_mbs))
                {
                    return MFX_ERR_UNDEFINED_BEHAVIOR;
                }
            }
            break;
        case 3:
        case 4:
        case 5:
            // For map types 3..5, number of slice groups must be 2
            if (pps->num_slice_groups != 2)
            {
                return MFX_ERR_UNDEFINED_BEHAVIOR;
            }
            pps->SliceGroupInfo.t2.slice_group_change_direction_flag = (mfxU8)Get1Bit();
            pps->SliceGroupInfo.t2.slice_group_change_rate = GetVLCElement(false) + 1;
            if (pps->SliceGroupInfo.t2.slice_group_change_rate > PicSizeInMapUnits)
            {
                return MFX_ERR_UNDEFINED_BEHAVIOR;
            }
            break;
        case 6:
            // mapping of slice group to map unit (macroblock if not fields) is
            // per map unit, read from bitstream
            {
                mfxU32 map_unit;
                mfxU32 num_bits;    // number of bits used to code each slice group id

                // number of map units, bitstream has value - 1
                pps->SliceGroupInfo.t3.pic_size_in_map_units = GetVLCElement(false) + 1;
                if (pps->SliceGroupInfo.t3.pic_size_in_map_units != PicSizeInMapUnits)
                {
                    return MFX_ERR_UNDEFINED_BEHAVIOR;
                }

                mfxI32 len = MSDK_MAX(1, pps->SliceGroupInfo.t3.pic_size_in_map_units);

                pps->SliceGroupInfo.pSliceGroupIDMap.resize(len);

                // num_bits is Ceil(log2(num_groups))
                num_bits = SGIdBits[pps->num_slice_groups - 2];

                for (map_unit = 0;
                     map_unit < pps->SliceGroupInfo.t3.pic_size_in_map_units;
                     map_unit++)
                {
                    pps->SliceGroupInfo.pSliceGroupIDMap[map_unit] = (mfxU8)GetBits(num_bits);
                    if (pps->SliceGroupInfo.pSliceGroupIDMap[map_unit] >
                        pps->num_slice_groups - 1)
                    {
                        return MFX_ERR_UNDEFINED_BEHAVIOR;
                    }
                }
            }
            break;
        default:
            return MFX_ERR_UNDEFINED_BEHAVIOR;

        }    // switch
    }    // slice group info

    // number of list 0 ref pics used to decode picture, bitstream has value - 1
    pps->num_ref_idx_l0_active = GetVLCElement(false) + 1;

    // number of list 1 ref pics used to decode picture, bitstream has value - 1
    pps->num_ref_idx_l1_active = GetVLCElement(false) + 1;

    if (pps->num_ref_idx_l1_active > MAX_NUM_REF_FRAMES || pps->num_ref_idx_l0_active > MAX_NUM_REF_FRAMES)
        return MFX_ERR_UNDEFINED_BEHAVIOR;

    // weighted pediction
    pps->weighted_pred_flag = (mfxU8)Get1Bit();
    pps->weighted_bipred_idc = (mfxU8)GetBits(2);

    // default slice QP, bitstream has value - 26
    mfxI32 pic_init_qp = GetVLCElement(true) + 26;
    pps->pic_init_qp = (mfxI8)pic_init_qp;

    // default SP/SI slice QP, bitstream has value - 26
    pps->pic_init_qs = (mfxU8)(GetVLCElement(true) + 26);
    pps->chroma_qp_index_offset[0] = (mfxI8)GetVLCElement(true);

    pps->deblocking_filter_variables_present_flag = (mfxU8)Get1Bit();
    pps->constrained_intra_pred_flag = (mfxU8)Get1Bit();
    pps->redundant_pic_cnt_present_flag = (mfxU8)Get1Bit();
    if (More_RBSP_Data())
    {
        pps->transform_8x8_mode_flag = (mfxU8) Get1Bit();
        if(sps->seq_scaling_matrix_present_flag)
        {
            //fall-back set rule B
            if(Get1Bit())
            {
                // 0
                if(Get1Bit())
                {
                    GetScalingList4x4(&pps->ScalingLists4x4[0],(mfxU8*)default_intra_scaling_list4x4,&pps->type_of_scaling_list_used[0]);
                }
                else
                {
                    FillScalingList4x4(&pps->ScalingLists4x4[0],(mfxU8*) sps->ScalingLists4x4[0].ScalingListCoeffs);
                    pps->type_of_scaling_list_used[0] = SCLDEFAULT;
                }
                // 1
                if(Get1Bit())
                {
                    GetScalingList4x4(&pps->ScalingLists4x4[1],(mfxU8*) default_intra_scaling_list4x4,&pps->type_of_scaling_list_used[1]);
                }
                else
                {
                    FillScalingList4x4(&pps->ScalingLists4x4[1],(mfxU8*) pps->ScalingLists4x4[0].ScalingListCoeffs);
                    pps->type_of_scaling_list_used[1] = SCLDEFAULT;
                }
                // 2
                if(Get1Bit())
                {
                    GetScalingList4x4(&pps->ScalingLists4x4[2],(mfxU8*) default_intra_scaling_list4x4,&pps->type_of_scaling_list_used[2]);
                }
                else
                {
                    FillScalingList4x4(&pps->ScalingLists4x4[2],(mfxU8*) pps->ScalingLists4x4[1].ScalingListCoeffs);
                    pps->type_of_scaling_list_used[2] = SCLDEFAULT;
                }
                // 3
                if(Get1Bit())
                {
                    GetScalingList4x4(&pps->ScalingLists4x4[3],(mfxU8*) default_inter_scaling_list4x4,&pps->type_of_scaling_list_used[3]);
                }
                else
                {
                    FillScalingList4x4(&pps->ScalingLists4x4[3],(mfxU8*) sps->ScalingLists4x4[3].ScalingListCoeffs);
                    pps->type_of_scaling_list_used[3] = SCLDEFAULT;
                }
                // 4
                if(Get1Bit())
                {
                    GetScalingList4x4(&pps->ScalingLists4x4[4],(mfxU8*) default_inter_scaling_list4x4,&pps->type_of_scaling_list_used[4]);
                }
                else
                {
                    FillScalingList4x4(&pps->ScalingLists4x4[4],(mfxU8*) pps->ScalingLists4x4[3].ScalingListCoeffs);
                    pps->type_of_scaling_list_used[4] = SCLDEFAULT;
                }
                // 5
                if(Get1Bit())
                {
                    GetScalingList4x4(&pps->ScalingLists4x4[5],(mfxU8*) default_inter_scaling_list4x4,&pps->type_of_scaling_list_used[5]);
                }
                else
                {
                    FillScalingList4x4(&pps->ScalingLists4x4[5],(mfxU8*) pps->ScalingLists4x4[4].ScalingListCoeffs);
                    pps->type_of_scaling_list_used[5] = SCLDEFAULT;
                }

                if (pps->transform_8x8_mode_flag)
                {
                    // 0
                    if(Get1Bit())
                    {
                        GetScalingList8x8(&pps->ScalingLists8x8[0],(mfxU8*)default_intra_scaling_list8x8,&pps->type_of_scaling_list_used[6]);
                    }
                    else
                    {
                        FillScalingList8x8(&pps->ScalingLists8x8[0],(mfxU8*) sps->ScalingLists8x8[0].ScalingListCoeffs);
                        pps->type_of_scaling_list_used[6] = SCLDEFAULT;
                    }
                    // 1
                    if(Get1Bit())
                    {
                        GetScalingList8x8(&pps->ScalingLists8x8[1],(mfxU8*) default_inter_scaling_list8x8,&pps->type_of_scaling_list_used[7]);
                    }
                    else
                    {
                        FillScalingList8x8(&pps->ScalingLists8x8[1],(mfxU8*) sps->ScalingLists8x8[1].ScalingListCoeffs);
                        pps->type_of_scaling_list_used[7] = SCLDEFAULT;
                    }
                }
            }
            else
            {
                mfxI32 i;
                for(i=0; i<6; i++)
                {
                    FillScalingList4x4(&pps->ScalingLists4x4[i],(mfxU8 *)sps->ScalingLists4x4[i].ScalingListCoeffs);
                    pps->type_of_scaling_list_used[i] = sps->type_of_scaling_list_used[i];
                }

                if (pps->transform_8x8_mode_flag)
                {
                    for(i=0; i<2; i++)
                    {
                        FillScalingList8x8(&pps->ScalingLists8x8[i],(mfxU8 *)sps->ScalingLists8x8[i].ScalingListCoeffs);
                        pps->type_of_scaling_list_used[i] = sps->type_of_scaling_list_used[i];
                    }
                }
            }
        }
        else
        {
            //fall-back set rule A
            if(Get1Bit())
            {
                // 0
                if(Get1Bit())
                {
                    GetScalingList4x4(&pps->ScalingLists4x4[0],(mfxU8*)default_intra_scaling_list4x4,&pps->type_of_scaling_list_used[0]);
                }
                else
                {
                    FillScalingList4x4(&pps->ScalingLists4x4[0],(mfxU8*) default_intra_scaling_list4x4);
                    pps->type_of_scaling_list_used[0] = SCLDEFAULT;
                }
                // 1
                if(Get1Bit())
                {
                    GetScalingList4x4(&pps->ScalingLists4x4[1],(mfxU8*) default_intra_scaling_list4x4,&pps->type_of_scaling_list_used[1]);
                }
                else
                {
                    FillScalingList4x4(&pps->ScalingLists4x4[1],(mfxU8*) pps->ScalingLists4x4[0].ScalingListCoeffs);
                    pps->type_of_scaling_list_used[1] = SCLDEFAULT;
                }
                // 2
                if(Get1Bit())
                {
                    GetScalingList4x4(&pps->ScalingLists4x4[2],(mfxU8*) default_intra_scaling_list4x4,&pps->type_of_scaling_list_used[2]);
                }
                else
                {
                    FillScalingList4x4(&pps->ScalingLists4x4[2],(mfxU8*) pps->ScalingLists4x4[1].ScalingListCoeffs);
                    pps->type_of_scaling_list_used[2] = SCLDEFAULT;
                }
                // 3
                if(Get1Bit())
                {
                    GetScalingList4x4(&pps->ScalingLists4x4[3],(mfxU8*)default_inter_scaling_list4x4,&pps->type_of_scaling_list_used[3]);
                }
                else
                {
                    FillScalingList4x4(&pps->ScalingLists4x4[3],(mfxU8*) default_inter_scaling_list4x4);
                    pps->type_of_scaling_list_used[3] = SCLDEFAULT;
                }
                // 4
                if(Get1Bit())
                {
                    GetScalingList4x4(&pps->ScalingLists4x4[4],(mfxU8*) default_inter_scaling_list4x4,&pps->type_of_scaling_list_used[4]);
                }
                else
                {
                    FillScalingList4x4(&pps->ScalingLists4x4[4],(mfxU8*) pps->ScalingLists4x4[3].ScalingListCoeffs);
                    pps->type_of_scaling_list_used[4] = SCLDEFAULT;
                }
                // 5
                if(Get1Bit())
                {
                    GetScalingList4x4(&pps->ScalingLists4x4[5],(mfxU8*) default_inter_scaling_list4x4,&pps->type_of_scaling_list_used[5]);
                }
                else
                {
                    FillScalingList4x4(&pps->ScalingLists4x4[5],(mfxU8*) pps->ScalingLists4x4[4].ScalingListCoeffs);
                    pps->type_of_scaling_list_used[5] = SCLDEFAULT;
                }

                if (pps->transform_8x8_mode_flag)
                {
                    // 0
                    if(Get1Bit())
                    {
                        GetScalingList8x8(&pps->ScalingLists8x8[0],(mfxU8*)default_intra_scaling_list8x8,&pps->type_of_scaling_list_used[6]);
                    }
                    else
                    {
                        FillScalingList8x8(&pps->ScalingLists8x8[0],(mfxU8*) default_intra_scaling_list8x8);
                        pps->type_of_scaling_list_used[6] = SCLDEFAULT;
                    }
                    // 1
                    if(Get1Bit())
                    {
                        GetScalingList8x8(&pps->ScalingLists8x8[1],(mfxU8*) default_inter_scaling_list8x8,&pps->type_of_scaling_list_used[7]);
                    }
                    else
                    {
                        FillScalingList8x8(&pps->ScalingLists8x8[1],(mfxU8*) default_inter_scaling_list8x8);
                        pps->type_of_scaling_list_used[7] = SCLDEFAULT;
                    }
                }
            }
            else
            {
                mfxI32 i;
                for(i=0; i<6; i++)
                {
                    FillScalingList4x4(&pps->ScalingLists4x4[i],(mfxU8 *)sps->ScalingLists4x4[i].ScalingListCoeffs);
                    pps->type_of_scaling_list_used[i] = sps->type_of_scaling_list_used[i];
                }

                if (pps->transform_8x8_mode_flag)
                {
                    for(i=0; i<2; i++)
                    {
                        FillScalingList8x8(&pps->ScalingLists8x8[i],(mfxU8 *)sps->ScalingLists8x8[i].ScalingListCoeffs);
                        pps->type_of_scaling_list_used[i] = sps->type_of_scaling_list_used[i];
                    }
                }
            }
        }
        pps->chroma_qp_index_offset[1] = (mfxI8)GetVLCElement(true);
    }
    else
    {
        pps->chroma_qp_index_offset[1] = pps->chroma_qp_index_offset[0];
        mfxI32 i;
        for(i=0; i<6; i++)
        {
            FillScalingList4x4(&pps->ScalingLists4x4[i],(mfxU8 *)sps->ScalingLists4x4[i].ScalingListCoeffs);
            pps->type_of_scaling_list_used[i] = sps->type_of_scaling_list_used[i];
        }

        if (pps->transform_8x8_mode_flag)
        {
            for(i=0; i<2; i++)
            {
                FillScalingList8x8(&pps->ScalingLists8x8[i],(mfxU8 *)sps->ScalingLists8x8[i].ScalingListCoeffs);
                pps->type_of_scaling_list_used[i] = sps->type_of_scaling_list_used[i];
            }
        }
    }
    // calculate level scale matrices

    //start DC first
    //to do: reduce the number of matrices (in fact 1 is enough)
    mfxI32 i;
    // now process other 4x4 matrices
    for (i = 0; i < 6; i++)
    {
        for (mfxI32 j = 0; j < 88; j++)
            for (mfxI32 k = 0; k < 16; k++)
            {
                mfxU32 level_scale = pps->ScalingLists4x4[i].ScalingListCoeffs[k]*pre_norm_adjust4x4[j%6][pre_norm_adjust_index4x4[k]];
                pps->m_LevelScale4x4[i].LevelScaleCoeffs[j][k] = (mfxI16) level_scale;
            }
    }

    // process remaining 8x8  matrices
    for (i = 0; i < 2; i++)
    {
        for (mfxI32 j = 0; j < 88; j++)
            for (mfxI32 k = 0; k < 64; k++)
            {

                mfxU32 level_scale = pps->ScalingLists8x8[i].ScalingListCoeffs[k]*pre_norm_adjust8x8[j%6][pre_norm_adjust_index8x8[k]];
                    pps->m_LevelScale8x8[i].LevelScaleCoeffs[j][k] = (mfxI16) level_scale;

            }
    }

    return MFX_ERR_NONE;
}    // GetPictureParamSet

mfxStatus AVCHeadersBitstream::GetNalUnitPrefix(AVCNalExtension *pExt, mfxU32 )
{
    mfxStatus ps = MFX_ERR_NONE;

    ps = GetNalUnitExtension(pExt);

    if (ps != MFX_ERR_NONE || !pExt->svc_extension_flag)
        return ps;

    return ps;
}

mfxStatus AVCHeadersBitstream::GetNalUnitExtension(AVCNalExtension *pExt)
{
    pExt->extension_present = 1;

    // decode the type of the extension
    pExt->svc_extension_flag = (mfxU8) GetBits(1);

    // decode SVC extension
    if (pExt->svc_extension_flag)
    {
        pExt->svc.idr_flag = (mfxU8) Get1Bit();
        pExt->svc.priority_id = (mfxU8) GetBits(6);
        pExt->svc.no_inter_layer_pred_flag = (mfxU8) Get1Bit();
        pExt->svc.dependency_id = (mfxU8) GetBits(3);
        pExt->svc.quality_id = (mfxU8) GetBits(4);
        pExt->svc.temporal_id = (mfxU8) GetBits(3);
        pExt->svc.use_ref_base_pic_flag = (mfxU8) Get1Bit();
        pExt->svc.discardable_flag = (mfxU8) Get1Bit();
        pExt->svc.output_flag = (mfxU8) Get1Bit();
        GetBits(2);
    }
    // decode MVC extension
    else
    {
        pExt->mvc.non_idr_flag = (mfxU8) Get1Bit();
        pExt->mvc.priority_id = (mfxU16) GetBits(6);
        pExt->mvc.view_id = (mfxU16) GetBits(10);
        pExt->mvc.temporal_id = (mfxU8) GetBits(3);
        pExt->mvc.anchor_pic_flag = (mfxU8) Get1Bit();
        pExt->mvc.inter_view_flag = (mfxU8) Get1Bit();
        GetBits(1);
    }

    return MFX_ERR_NONE;

}

// ---------------------------------------------------------------------------
//    Read H.264 first part of slice header
//
//  Reading the rest of the header requires info in the picture and sequence
//  parameter sets referred to by this slice header.
//
//    Do not print debug messages when IsSearch is true. In that case the function
//    is being used to find the next compressed frame, errors may occur and should
//    not be reported.
//
// ---------------------------------------------------------------------------
mfxStatus AVCHeadersBitstream::GetSliceHeaderPart1(AVCSliceHeader *hdr)
{
    mfxU32 val;

    // decode NAL extension
    if (NAL_UT_CODED_SLICE_EXTENSION == hdr->nal_unit_type)
    {
        GetNalUnitExtension(&hdr->nal_ext);

        // set the IDR flag
        if (hdr->nal_ext.svc_extension_flag)
        {
            hdr->IdrPicFlag = hdr->nal_ext.svc.idr_flag;
        }
        else
        {
            hdr->view_id = hdr->nal_ext.mvc.view_id;
            hdr->IdrPicFlag = hdr->nal_ext.mvc.non_idr_flag ^ 1;
        }
    }
    else
    {
        hdr->IdrPicFlag = (NAL_UT_IDR_SLICE == hdr->nal_unit_type) ? (1) : (0);
        hdr->nal_ext.mvc.anchor_pic_flag = (mfxU8) hdr->IdrPicFlag ? 1 : 0;
        hdr->nal_ext.mvc.inter_view_flag = (mfxU8) 1;
    }

    hdr->first_mb_in_slice = GetVLCElement(false);
    if (0 > hdr->first_mb_in_slice) // upper bound is checked in AVCSlice
        return MFX_ERR_UNDEFINED_BEHAVIOR;

    // slice type
    val = GetVLCElement(false);
    if (val > S_INTRASLICE)
    {
        if (val > S_INTRASLICE + S_INTRASLICE + 1)
        {
            return MFX_ERR_UNDEFINED_BEHAVIOR;
        }
        else
        {
            // Slice type is specifying type of not only this but all remaining
            // slices in the picture. Since slice type is always present, this bit
            // of info is not used in our implementation. Adjust (just shift range)
            // and return type without this extra info.
            val -= (S_INTRASLICE + 1);
        }
    }

    if (val > INTRASLICE) // all other doesn't support
        return MFX_ERR_UNDEFINED_BEHAVIOR;

    hdr->slice_type = (EnumSliceCodType)val;

    mfxU32 pic_parameter_set_id = GetVLCElement(false);
    hdr->pic_parameter_set_id = (mfxU16)pic_parameter_set_id;
    if (pic_parameter_set_id > MAX_NUM_PIC_PARAM_SETS - 1)
    {
        return MFX_ERR_UNDEFINED_BEHAVIOR;
    }

    return MFX_ERR_NONE;
} // mfxStatus GetSliceHeaderPart1(AVCSliceHeader *pSliceHeader)

mfxStatus AVCHeadersBitstream::GetSliceHeaderPart2(
    AVCSliceHeader *hdr,        // slice header read goes here
    const AVCPicParamSet *pps,
    const AVCSeqParamSet *sps)            // from slice header NAL unit
{
    hdr->frame_num = GetBits(sps->log2_max_frame_num);

    hdr->bottom_field_flag = 0;
    if (sps->frame_mbs_only_flag == 0)
    {
        hdr->field_pic_flag = (mfxU8)Get1Bit();
        hdr->MbaffFrameFlag = !hdr->field_pic_flag && sps->mb_adaptive_frame_field_flag;
        if (hdr->field_pic_flag != 0)
        {
            hdr->bottom_field_flag = (mfxU8)Get1Bit();
        }
    }

    // correct frst_mb_in_slice in order to handle MBAFF
    if (hdr->MbaffFrameFlag && hdr->first_mb_in_slice)
        hdr->first_mb_in_slice <<= 1;

    if (hdr->IdrPicFlag)
    {
        mfxI32 pic_id = hdr->idr_pic_id = GetVLCElement(false);
        if (pic_id < 0 || pic_id > 65535)
            return MFX_ERR_UNDEFINED_BEHAVIOR;
    }

    if (sps->pic_order_cnt_type == 0)
    {
        hdr->pic_order_cnt_lsb = GetBits(sps->log2_max_pic_order_cnt_lsb);
        if (pps->pic_order_present_flag && (!hdr->field_pic_flag))
            hdr->delta_pic_order_cnt_bottom = GetVLCElement(true);
    }

    if ((sps->pic_order_cnt_type == 1) && (sps->delta_pic_order_always_zero_flag == 0))
    {
        hdr->delta_pic_order_cnt[0] = GetVLCElement(true);
        if (pps->pic_order_present_flag && (!hdr->field_pic_flag))
            hdr->delta_pic_order_cnt[1] = GetVLCElement(true);
    }

    if (pps->redundant_pic_cnt_present_flag)
    {
        // redundant pic count
        hdr->redundant_pic_cnt = GetVLCElement(false);
        if (hdr->redundant_pic_cnt > 127)
            return MFX_ERR_UNDEFINED_BEHAVIOR;
    }

    return MFX_ERR_NONE;
}

// ---------------------------------------------------------------------------
//    Read H.264 second part of slice header
//
//    Do not print debug messages when IsSearch is true. In that case the function
//    is being used to find the next compressed frame, errors may occur and should
//    not be reported.
// ---------------------------------------------------------------------------

mfxStatus AVCHeadersBitstream::GetSliceHeaderPart3(
    AVCSliceHeader *hdr,        // slice header read goes here
    PredWeightTable *pPredWeight_L0, // L0 weight table goes here
    PredWeightTable *pPredWeight_L1, // L1 weight table goes here
    RefPicListReorderInfo *pReorderInfo_L0,
    RefPicListReorderInfo *pReorderInfo_L1,
    AdaptiveMarkingInfo *pAdaptiveMarkingInfo,
    const AVCPicParamSet *pps,
    const AVCSeqParamSet *sps,
    mfxU8 NALRef_idc)            // from slice header NAL unit
{
    mfxU8 ref_pic_list_reordering_flag_l0 = 0;
    mfxU8 ref_pic_list_reordering_flag_l1 = 0;

    if (BPREDSLICE == hdr->slice_type)
    {
        // direct mode prediction method
        hdr->direct_spatial_mv_pred_flag = (mfxU8)Get1Bit();
    }

    if (PREDSLICE == hdr->slice_type ||
        S_PREDSLICE == hdr->slice_type ||
        BPREDSLICE == hdr->slice_type)
    {
        hdr->num_ref_idx_active_override_flag = (mfxU8)Get1Bit();
        if (hdr->num_ref_idx_active_override_flag != 0)
        // ref idx active l0 and l1
        {
            hdr->num_ref_idx_l0_active = GetVLCElement(false) + 1;
            if (BPREDSLICE == hdr->slice_type)
                hdr->num_ref_idx_l1_active = GetVLCElement(false) + 1;
        }
        else
        {
            // no overide, use num active from pic param set
            hdr->num_ref_idx_l0_active = pps->num_ref_idx_l0_active;
            if (BPREDSLICE == hdr->slice_type)
                hdr->num_ref_idx_l1_active = pps->num_ref_idx_l1_active;
            else
                hdr->num_ref_idx_l1_active = 0;
        }
    }    // ref idx override

    if (hdr->num_ref_idx_l1_active > MAX_NUM_REF_FRAMES || hdr->num_ref_idx_l0_active > MAX_NUM_REF_FRAMES)
        return MFX_ERR_UNDEFINED_BEHAVIOR;

    if (hdr->slice_type != INTRASLICE && hdr->slice_type != S_INTRASLICE)
    {
        mfxU32 reordering_of_pic_nums_idc;
        mfxU32 reorder_idx;

        // Reference picture list reordering
        ref_pic_list_reordering_flag_l0 = (mfxU8)Get1Bit();
        if (ref_pic_list_reordering_flag_l0)
        {
            bool bOk = true;

            reorder_idx = 0;
            reordering_of_pic_nums_idc = 0;

            // Get reorder idc,pic_num pairs until idc==3
            while (bOk)
            {
                reordering_of_pic_nums_idc = (mfxU8)GetVLCElement(false);
                if (reordering_of_pic_nums_idc > 5)
                    return MFX_ERR_UNDEFINED_BEHAVIOR;

                if (reordering_of_pic_nums_idc == 3)
                    break;

                if (reorder_idx >= MAX_NUM_REF_FRAMES)
                {
                    return MFX_ERR_UNDEFINED_BEHAVIOR;
                }

                pReorderInfo_L0->reordering_of_pic_nums_idc[reorder_idx] =
                                            (mfxU8)reordering_of_pic_nums_idc;
                pReorderInfo_L0->reorder_value[reorder_idx]  =
                                                    GetVLCElement(false);
                if (reordering_of_pic_nums_idc != 2)
                    // abs_diff_pic_num is coded minus 1
                    pReorderInfo_L0->reorder_value[reorder_idx]++;
                reorder_idx++;
            }    // while

            pReorderInfo_L0->num_entries = reorder_idx;
        }    // L0 reordering info
        else
            pReorderInfo_L0->num_entries = 0;

        if (BPREDSLICE == hdr->slice_type)
        {
            ref_pic_list_reordering_flag_l1 = (mfxU8)Get1Bit();
            if (ref_pic_list_reordering_flag_l1)
            {
                bool bOk = true;

                // Get reorder idc,pic_num pairs until idc==3
                reorder_idx = 0;
                reordering_of_pic_nums_idc = 0;
                while (bOk)
                {
                    reordering_of_pic_nums_idc = GetVLCElement(false);
                    if (reordering_of_pic_nums_idc > 5)
                        return MFX_ERR_UNDEFINED_BEHAVIOR;

                    if (reordering_of_pic_nums_idc == 3)
                        break;

                    if (reorder_idx >= MAX_NUM_REF_FRAMES)
                    {
                        return MFX_ERR_UNDEFINED_BEHAVIOR;
                    }

                    pReorderInfo_L1->reordering_of_pic_nums_idc[reorder_idx] =
                                                (mfxU8)reordering_of_pic_nums_idc;
                    pReorderInfo_L1->reorder_value[reorder_idx]  =
                                                        GetVLCElement(false);
                    if (reordering_of_pic_nums_idc != 2)
                        // abs_diff_pic_num is coded minus 1
                        pReorderInfo_L1->reorder_value[reorder_idx]++;
                    reorder_idx++;
                }    // while
                pReorderInfo_L1->num_entries = reorder_idx;
            }    // L1 reordering info
            else
                pReorderInfo_L1->num_entries = 0;

        }    // B slice
    }    // reordering info

    // prediction weight table
    if ( (pps->weighted_pred_flag &&
          ((PREDSLICE == hdr->slice_type) || (S_PREDSLICE == hdr->slice_type))) ||
         ((pps->weighted_bipred_idc == 1) && (BPREDSLICE == hdr->slice_type)))
    {
        hdr->luma_log2_weight_denom = (mfxU8)GetVLCElement(false);
        if (sps->chroma_format_idc != 0)
            hdr->chroma_log2_weight_denom = (mfxU8)GetVLCElement(false);

        for (mfxI32 refindex = 0; refindex < hdr->num_ref_idx_l0_active; refindex++)
        {
            pPredWeight_L0[refindex].luma_weight_flag = (mfxU8)Get1Bit();
            if (pPredWeight_L0[refindex].luma_weight_flag)
            {
                pPredWeight_L0[refindex].luma_weight = (mfxI8)GetVLCElement(true);
                pPredWeight_L0[refindex].luma_offset = (mfxI8)GetVLCElement(true);
            }
            else
            {
                pPredWeight_L0[refindex].luma_weight = (mfxI8)(1 << hdr->luma_log2_weight_denom);
                pPredWeight_L0[refindex].luma_offset = 0;
            }

            if (sps->chroma_format_idc != 0)
            {
                pPredWeight_L0[refindex].chroma_weight_flag = (mfxU8)Get1Bit();
                if (pPredWeight_L0[refindex].chroma_weight_flag)
                {
                    pPredWeight_L0[refindex].chroma_weight[0] = (mfxI8)GetVLCElement(true);
                    pPredWeight_L0[refindex].chroma_offset[0] = (mfxI8)GetVLCElement(true);
                    pPredWeight_L0[refindex].chroma_weight[1] = (mfxI8)GetVLCElement(true);
                    pPredWeight_L0[refindex].chroma_offset[1] = (mfxI8)GetVLCElement(true);
                }
                else
                {
                    pPredWeight_L0[refindex].chroma_weight[0] = (mfxI8)(1 << hdr->chroma_log2_weight_denom);
                    pPredWeight_L0[refindex].chroma_weight[1] = (mfxI8)(1 << hdr->chroma_log2_weight_denom);
                    pPredWeight_L0[refindex].chroma_offset[0] = 0;
                    pPredWeight_L0[refindex].chroma_offset[1] = 0;
                }
            }
        }

        if (BPREDSLICE == hdr->slice_type)
        {
            for (mfxI32 refindex = 0; refindex < hdr->num_ref_idx_l1_active; refindex++)
            {
                pPredWeight_L1[refindex].luma_weight_flag = (mfxU8)Get1Bit();
                if (pPredWeight_L1[refindex].luma_weight_flag)
                {
                    pPredWeight_L1[refindex].luma_weight = (mfxI8)GetVLCElement(true);
                    pPredWeight_L1[refindex].luma_offset = (mfxI8)GetVLCElement(true);
                }
                else
                {
                    pPredWeight_L1[refindex].luma_weight = (mfxI8)(1 << hdr->luma_log2_weight_denom);
                    pPredWeight_L1[refindex].luma_offset = 0;
                }

                if (sps->chroma_format_idc != 0)
                {
                    pPredWeight_L1[refindex].chroma_weight_flag = (mfxU8)Get1Bit();
                    if (pPredWeight_L1[refindex].chroma_weight_flag)
                    {
                        pPredWeight_L1[refindex].chroma_weight[0] = (mfxI8)GetVLCElement(true);
                        pPredWeight_L1[refindex].chroma_offset[0] = (mfxI8)GetVLCElement(true);
                        pPredWeight_L1[refindex].chroma_weight[1] = (mfxI8)GetVLCElement(true);
                        pPredWeight_L1[refindex].chroma_offset[1] = (mfxI8)GetVLCElement(true);
                    }
                    else
                    {
                        pPredWeight_L1[refindex].chroma_weight[0] = (mfxI8)(1 << hdr->chroma_log2_weight_denom);
                        pPredWeight_L1[refindex].chroma_weight[1] = (mfxI8)(1 << hdr->chroma_log2_weight_denom);
                        pPredWeight_L1[refindex].chroma_offset[0] = 0;
                        pPredWeight_L1[refindex].chroma_offset[1] = 0;
                    }
                }
            }
        }    // B slice
    }    // prediction weight table
    else
    {
        hdr->luma_log2_weight_denom = 0;
        hdr->chroma_log2_weight_denom = 0;
    }

    // dec_ref_pic_marking
    pAdaptiveMarkingInfo->num_entries = 0;

    if (NALRef_idc)
    {
        if (hdr->IdrPicFlag)
        {
            hdr->no_output_of_prior_pics_flag = (mfxU8)Get1Bit();
            hdr->long_term_reference_flag = (mfxU8)Get1Bit();
        }
        else
        {
            mfxU32 memory_management_control_operation;
            mfxU32 num_entries = 0;

            hdr->adaptive_ref_pic_marking_mode_flag = (mfxU8)Get1Bit();
            while (hdr->adaptive_ref_pic_marking_mode_flag != 0)
            {
                memory_management_control_operation = (mfxU8)GetVLCElement(false);
                if (memory_management_control_operation == 0)
                    break;

                if (memory_management_control_operation > 6)
                    return MFX_ERR_UNDEFINED_BEHAVIOR;

                pAdaptiveMarkingInfo->mmco[num_entries] =
                    (mfxU8)memory_management_control_operation;
                if (memory_management_control_operation != 5)
                     pAdaptiveMarkingInfo->value[num_entries*2] =
                        GetVLCElement(false);
                // Only mmco 3 requires 2 values
                if (memory_management_control_operation == 3)
                     pAdaptiveMarkingInfo->value[num_entries*2+1] =
                        GetVLCElement(false);
                num_entries++;
                if (num_entries >= MAX_NUM_REF_FRAMES)
                {
                    return MFX_ERR_UNDEFINED_BEHAVIOR;
                }
            }    // while
            pAdaptiveMarkingInfo->num_entries = num_entries;
        }
    }    // def_ref_pic_marking

    if (pps->entropy_coding_mode == 1  &&    // CABAC
        (hdr->slice_type != INTRASLICE && hdr->slice_type != S_INTRASLICE))
        hdr->cabac_init_idc = GetVLCElement(false);
    else
        hdr->cabac_init_idc = 0;

    if (hdr->cabac_init_idc > 2)
        return MFX_ERR_UNDEFINED_BEHAVIOR;

    hdr->slice_qp_delta = GetVLCElement(true);

    if (S_PREDSLICE == hdr->slice_type ||
        S_INTRASLICE == hdr->slice_type)
    {
        if (S_PREDSLICE == hdr->slice_type)
            hdr->sp_for_switch_flag = (mfxU8)Get1Bit();
        hdr->slice_qs_delta = GetVLCElement(true);
    }

    if (pps->deblocking_filter_variables_present_flag != 0)
    {
        // deblock filter flag and offsets
        hdr->disable_deblocking_filter_idc = GetVLCElement(false);
        if (hdr->disable_deblocking_filter_idc > 2)
            return MFX_ERR_UNDEFINED_BEHAVIOR;

        if (hdr->disable_deblocking_filter_idc != 1)
        {
            hdr->slice_alpha_c0_offset = GetVLCElement(true)<<1;
            hdr->slice_beta_offset = GetVLCElement(true)<<1;

            if (hdr->slice_alpha_c0_offset < -12 || hdr->slice_alpha_c0_offset > 12)
            {
                return MFX_ERR_UNDEFINED_BEHAVIOR;
            }

            if (hdr->slice_beta_offset < -12 || hdr->slice_beta_offset > 12)
            {
                return MFX_ERR_UNDEFINED_BEHAVIOR;
            }
        }
        else
        {
            // set filter offsets to max values to disable filter
            hdr->slice_alpha_c0_offset = (mfxI8)(0 - AVC_QP_MAX);
            hdr->slice_beta_offset = (mfxI8)(0 - AVC_QP_MAX);
        }
    }

    if (pps->num_slice_groups > 1 &&
        pps->SliceGroupInfo.slice_group_map_type >= 3 &&
        pps->SliceGroupInfo.slice_group_map_type <= 5)
    {
        mfxU32 num_bits;    // number of bits used to code slice_group_change_cycle
        mfxU32 val;
        mfxU32 pic_size_in_map_units;
        mfxU32 max_slice_group_change_cycle=0;

        // num_bits is Ceil(log2(picsizeinmapunits/slicegroupchangerate + 1))
        pic_size_in_map_units = sps->frame_width_in_mbs * sps->frame_height_in_mbs;

        max_slice_group_change_cycle = pic_size_in_map_units /
                        pps->SliceGroupInfo.t2.slice_group_change_rate;
        if (pic_size_in_map_units %
                        pps->SliceGroupInfo.t2.slice_group_change_rate)
            max_slice_group_change_cycle++;

        val = max_slice_group_change_cycle;
        num_bits = 0;
        while (val)
        {
            num_bits++;
            val >>= 1;
        }
        hdr->slice_group_change_cycle = GetBits(num_bits);
    }

    return MFX_ERR_NONE;
} // GetSliceHeaderPart3()

void AVCHeadersBitstream::GetScalingList4x4(AVCScalingList4x4 *scl, mfxU8 *def, mfxU8 *scl_type)
{
    mfxU32 lastScale = 8;
    mfxU32 nextScale = 8;
    bool DefaultMatrix = false;
    mfxI32 j;

    for (j = 0; j < 16; j++ )
    {
        if (nextScale != 0)
        {
            mfxI32 delta_scale  = GetVLCElement(true);
            if (delta_scale < -128 || delta_scale > 127)
                throw AVC_exception(MFX_ERR_UNDEFINED_BEHAVIOR);
            nextScale = ( lastScale + delta_scale + 256 ) & 0xff;
            DefaultMatrix = ( j == 0 && nextScale == 0 );
        }
        scl->ScalingListCoeffs[ mp_scan4x4[0][j] ] = ( nextScale == 0 ) ? (mfxU8)lastScale : (mfxU8)nextScale;
        lastScale = scl->ScalingListCoeffs[ mp_scan4x4[0][j] ];
    }
    if (!DefaultMatrix)
    {
        *scl_type = SCLREDEFINED;
        return;
    }
    *scl_type= SCLDEFAULT;
    FillScalingList4x4(scl,def);
    return;
}

void AVCHeadersBitstream::GetScalingList8x8(AVCScalingList8x8 *scl, mfxU8 *def, mfxU8 *scl_type)
{
    mfxU32 lastScale = 8;
    mfxU32 nextScale = 8;
    bool DefaultMatrix=false;
    mfxI32 j;

    for (j = 0; j < 64; j++ )
    {
        if (nextScale != 0)
        {
            mfxI32 delta_scale  = GetVLCElement(true);
            if (delta_scale < -128 || delta_scale > 127)
                throw AVC_exception(MFX_ERR_UNDEFINED_BEHAVIOR);
            nextScale = ( lastScale + delta_scale + 256 ) & 0xff;
            DefaultMatrix = ( j == 0 && nextScale == 0 );
        }
        scl->ScalingListCoeffs[ hp_scan8x8[0][j] ] = ( nextScale == 0 ) ? (mfxU8)lastScale : (mfxU8)nextScale;
        lastScale = scl->ScalingListCoeffs[ hp_scan8x8[0][j] ];
    }
    if (!DefaultMatrix)
    {
        *scl_type=SCLREDEFINED;
        return;
    }
    *scl_type= SCLDEFAULT;
    FillScalingList8x8(scl,def);
    return;

}

void SetDefaultScalingLists(AVCSeqParamSet * sps)
{
    mfxI32 i;

    for (i = 0; i < 6; i += 1)
    {
        FillFlatScalingList4x4(&sps->ScalingLists4x4[i]);
    }
    for (i = 0; i < 2; i += 1)
    {
        FillFlatScalingList8x8(&sps->ScalingLists8x8[i]);
    }
}

mfxStatus DecodeExpGolombOne(mfxU32 **ppBitStream, mfxI32 *pBitOffset,
                                                      mfxI32 *pDst,
                                                      mfxI32 isSigned)
{
    mfxU32 code;
    mfxU32 info     = 0;
    mfxI32 length   = 1;            /* for first bit read above*/
    mfxU32 thisChunksLength = 0;
    mfxU32 sval;

    /* Fast check for element = 0 */
    avcGetNBits((*ppBitStream), (*pBitOffset), 1, code);
    if (code)
    {
        *pDst = 0;
        return MFX_ERR_NONE;
    }

    avcGetNBits((*ppBitStream), (*pBitOffset), 8, code);
    length += 8;

    /* find nonzero byte */
    while (code == 0)
    {
        avcGetNBits((*ppBitStream), (*pBitOffset), 8, code);
        length += 8;
    }

    /* find leading '1' */
    while ((code & 0x80) == 0)
    {
        code <<= 1;
        thisChunksLength++;
    }
    length -= 8 - thisChunksLength;

    avcUngetNBits((*ppBitStream), (*pBitOffset), 8 - (thisChunksLength + 1));

    /* Get info portion of codeword */
    if (length)
    {
        avcGetNBits((*ppBitStream), (*pBitOffset),length, info);
    }

    sval = (1 << length) + info - 1;
    if (isSigned)
    {
        if (sval & 1)
            *pDst = (mfxI32) ((sval + 1) >> 1);
        else
            *pDst = -((mfxI32) (sval >> 1));
    }
    else
        *pDst = (mfxI32) sval;

    return MFX_ERR_NONE;
}

mfxI32 AVCHeadersBitstream::GetSEI(const HeaderSet<AVCSeqParamSet> & sps, mfxI32 current_sps, AVCSEIPayLoad *spl)
{
    mfxU32 code;
    mfxI32 payloadType = 0;

    avcNextBits(m_pbs, m_bitOffset, 8, code);
    while (code  ==  0xFF)
    {
        /* fixed-pattern bit string using 8 bits written equal to 0xFF */
        avcGetNBits(m_pbs, m_bitOffset, 8, code);
        payloadType += 255;
        avcNextBits(m_pbs, m_bitOffset, 8, code);
    }

    mfxI32 last_payload_type_byte;
    avcGetNBits(m_pbs, m_bitOffset, 8, last_payload_type_byte);

    payloadType += last_payload_type_byte;

    mfxI32 payloadSize = 0;

    avcNextBits(m_pbs, m_bitOffset, 8, code);
    while( code  ==  0xFF )
    {
        /* fixed-pattern bit string using 8 bits written equal to 0xFF */
        avcGetNBits(m_pbs, m_bitOffset, 8, code);
        payloadSize += 255;
        avcNextBits(m_pbs, m_bitOffset, 8, code);
    }

    mfxI32 last_payload_size_byte;

    avcGetNBits(m_pbs, m_bitOffset, 8, last_payload_size_byte);
    payloadSize += last_payload_size_byte;
    spl->Reset();
    spl->payLoadSize = payloadSize;

    if (payloadType < 0 || payloadType > SEI_RESERVED)
        payloadType = SEI_RESERVED;

    spl->payLoadType = (SEI_TYPE)payloadType;

    if (spl->payLoadSize > BytesLeft())
    {
        throw AVC_exception(MFX_ERR_UNDEFINED_BEHAVIOR);
    }

    mfxU32 * pbs;
    mfxU32 bitOffsetU;
    mfxI32 bitOffset;

    pbs       = m_pbs;
    bitOffsetU = m_bitOffset;
    bitOffset = bitOffsetU;

    mfxI32 ret = GetSEIPayload(sps, current_sps, spl);

    for (mfxU32 i = 0; i < spl->payLoadSize; i++)
    {
        avcSkipNBits(pbs, bitOffset, 8);
    }

    m_pbs = pbs;
    m_bitOffset = bitOffset;

    return ret;
}

mfxI32 AVCHeadersBitstream::GetSEIPayload(const HeaderSet<AVCSeqParamSet> & sps, mfxI32 current_sps, AVCSEIPayLoad *spl)
{
    switch (spl->payLoadType)
    {
    case SEI_RECOVERY_POINT_TYPE:
        return recovery_point(sps,current_sps,spl);
    default:
        return reserved_sei_message(sps,current_sps,spl);
    }
}

mfxI32 AVCHeadersBitstream::reserved_sei_message(const HeaderSet<AVCSeqParamSet> & , mfxI32 current_sps, AVCSEIPayLoad *spl)
{
    for (mfxU32 i = 0; i < spl->payLoadSize; i++)
        avcSkipNBits(m_pbs, m_bitOffset, 8)
    AlignPointerRight();
    return current_sps;
}

mfxI32 AVCHeadersBitstream::recovery_point(const HeaderSet<AVCSeqParamSet> & , mfxI32 current_sps, AVCSEIPayLoad *spl)
{
    AVCSEIPayLoad::SEIMessages::RecoveryPoint * recPoint = &(spl->SEI_messages.recovery_point);

    recPoint->recovery_frame_cnt = (mfxU8)GetVLCElement(false);

    recPoint->exact_match_flag = (mfxU8)Get1Bit();
    recPoint->broken_link_flag = (mfxU8)Get1Bit();
    recPoint->changing_slice_group_idc = (mfxU8)GetBits(2);

    if (recPoint->changing_slice_group_idc > 2)
        return -1;

    return current_sps;
}

void HeapObject::Free()
{
}

} // namespace AVCParser

